package com.gree.kundada.utils;


import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.gree.kundada.exception.BusinessException;
import com.gree.kundada.model.entity.CurrentUser;
import com.gree.kundada.model.vo.LoginUserVO;
import com.gree.kundada.exception.BusinessException;
import com.gree.kundada.model.entity.CurrentUser;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Date;
import java.util.concurrent.TimeUnit;

import static com.gree.kundada.common.ErrorCode.NOT_LOGIN_ERROR;

/**
 * token工具类
 */
@Component
public class TokenUtils {

    //注入redis模板
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Value("${token.expire-time}")
    private int expireTime;

    /**
     * 常量:
     */
    //token中存放用户id
    private static final String CLAIM_NAME_ID = "CLAIM_NAME_ID";
    //token中存放用户名对应的账户
    private static final String CLAIM_NAME_ACCOUNT = "CLAIM_NAME_ACCOUNT";
    //token中存放用户对应的昵称
    private static final String CLAIM_NAME_NAME = "CLAIM_NAME_NAME";
    //token中存放用户对应的角色
    private static final String CLAIM_NAME_ROLE = "CLAIM_NAME_ROLE";

    private String sign(LoginUserVO currentUser, String securityKey){
        String token = JWT.create()
                .withClaim(CLAIM_NAME_ID, currentUser.getId())
                .withClaim(CLAIM_NAME_ACCOUNT, currentUser.getUserAccount())
                .withClaim(CLAIM_NAME_NAME, currentUser.getUserName())
                .withClaim(CLAIM_NAME_ROLE, currentUser.getUserRole())
                .withIssuedAt(new Date())//发行时间
                .withExpiresAt(new Date(System.currentTimeMillis() + expireTime *1000))//有效时间
                .sign(Algorithm.HMAC256(securityKey));
        return token;
    }

    /**
     * 将当前用户信息以用户密码为密钥生成token的方法
     */
    public String loginSign(LoginUserVO currentUser, String password){
        //生成token
        String token = sign(currentUser, password);
        //将token保存到redis中,并设置token在redis中的过期时间
        stringRedisTemplate.opsForValue().set("kundada:user:"+currentUser.getUserAccount(), token, expireTime, TimeUnit.SECONDS);
        return token;
    }

    /**
     * 从客户端归还的token中获取用户信息的方法
     */
    public CurrentUser getCurrentUser(String token) {
        if(StringUtils.isEmpty(token)){
            throw new BusinessException(NOT_LOGIN_ERROR);
        }
        //对token进行解码,获取解码后的token
        DecodedJWT decodedJWT = null;
        try {
            decodedJWT = JWT.decode(token);
        } catch (JWTDecodeException e) {
            throw new BusinessException(NOT_LOGIN_ERROR);
        }
        //从解码后的token中获取用户信息并封装到CurrentUser对象中返回
        Long id = Long.valueOf(decodedJWT.getClaim(CLAIM_NAME_ID).asInt());//用户账号id
        String userAccount = decodedJWT.getClaim(CLAIM_NAME_ACCOUNT).asString();//用户账号
        String userName = decodedJWT.getClaim(CLAIM_NAME_NAME).asString();//用户姓名
        String userRole = decodedJWT.getClaim(CLAIM_NAME_ROLE).asString();//用户角色
        if (StringUtils.isAnyBlank(userAccount, userName, userRole)) {
            throw new BusinessException(NOT_LOGIN_ERROR);
        }
        return new CurrentUser(id, userAccount, userName, userRole);
    }

}
